// 3. 编译模板：处理视图中的DOM
// 3.1 如el中的子节点的{{mag}}
// <p>{{msg}}</p>
// 3.2 如el中的子节点的指令属性
// <p v-text="msg"></p>
// 3.3 处理data数据

// 要el data

function Compiler(vm) {
  this.$vm = vm
  this.compile(this.$vm.$el)
}

// 编译模板
Compiler.prototype.compile = function (el) {
  // 编译类型
  // console.log(el.childNodes) 
  // Array.from 把伪数组转化数组
  Array.from(el.childNodes).forEach(node => {
    if (this.isTextNode(node)) {
      this.compilerTextNode(node)
    }
    if(this.isElementNode(node)) {
      this.compilerElementNode(node)
      // 如果下面还有子元素
      this.compile(node)
    }
  })

  
}


// 核心函数
// 编译文本节点 

// <p>{{msg}}</p>  -> <p>abc</p>
// 1. node.textContent   {{msg}}
// 2. 判断{{}}
// 3. 提取msg
// 4. 赋值
Compiler.prototype.compilerTextNode = function (node) { 
    const txt = node.textContent //"{{msg}}"
    // + 一个或者多个
    // . 匹配到连续的字符
    const reg = /\{\{(.+)\}\}/
    if(reg.test(txt)) {
      //RegExp.$1是RegExp的一个属性,指的是与正则表达式匹配bai的第一du个 子匹配(以括号为标志)字符串，以此类推，RegExp.$2，RegExp.$3，..RegExp.$99总共可以有99个匹配
      const key = RegExp.$1.trim()
      // 第一次默认赋值
      node.textContent = this.$vm.$data[key]

      // 注册事件 bus  来自eventEmitter.js
      // 改数据时为修改dom值注册事件
      bus.$on(key , ()=> {
        node.textContent = this.$vm.$data[key]
      })
    }
}

// 编译元素节点
// <p v-text='msg'></p>   ->  <p>abc</p>
// <input v-model='msg'>  ->  input的value值
// 1. 找到所有的属性attrbutes
// 2. 判断指令属性
// 3. 处理具体的某个指令
Compiler.prototype.compilerElementNode = function (node) {
  // console.dir(node)
  Array.from(node.attributes).forEach( attr => {

    const attrName = attr.name //v-model  v-text
    const value = attr.value   //msg  age
    if(this.isDirective(attrName)) {

       if(attrName === 'v-text') {
          node.textContent = this.$vm.$data[value]
          // 注册事件
          bus.$on(value , ()=> {
            node.textContent = this.$vm.$data[value]
          })
       }

      // v-model -> :value=""  @input='fn'  
       if(attrName === 'v-model') {
        node.value = this.$vm.$data[value]
        // 注册事件 
        bus.$on(value , ()=> {
          node.value = this.$vm.$data[value]
        })

        // node -> inputDOM -> 绑定input事件
        node.oninput = () => {
          this.$vm.$data[value] = node.value
        }
       }
    }
  })
}


// 辅助函数
// 判断不同类型的节点
// 文本节点
Compiler.prototype.isTextNode = function (node) {
    return node.nodeType === 3
}

// 元素节点
Compiler.prototype.isElementNode = function (node) {
  return node.nodeType === 1
}

// 判断属性名字是否是指令
Compiler.prototype.isDirective = function (attrName) {
  return attrName.startsWith('v-')
}